
enum HandShape {
    Rock,
    Paper,
    Scissors,
}

impl HandShape {
    fn score(&self) -> i32 {
        match self {
            Self::Rock => 1,
            Self::Paper => 2,
            Self::Scissors => 3,
        }
    }

    fn fight_with(&self, other: &HandShape) -> i32 {
        match self {
            Self::Rock => {
                match other {
                    Self::Rock => 3,
                    Self::Paper => 0,
                    Self::Scissors => 6,
                }
            }
            Self::Paper => {
                match other {
                    Self::Rock => 6,
                    Self::Paper => 3,
                    Self::Scissors => 0,
                }
            }
            Self::Scissors => {
                match other {
                    Self::Rock => 0,
                    Self::Paper => 6,
                    Self::Scissors => 3,
                }
            }
        }
    }

    fn play_game(&self, other: &HandShape) -> i32 {
        self.score() + self.fight_with(other)
    }
}

fn parse_input() -> Vec<(HandShape, HandShape)> {
    let input = include_str!("../input.txt");
    input
        .lines()
        .map(|line| -> (HandShape, HandShape) {
            let hs1 = match &line[0..1] {
                "A" => HandShape::Rock,
                "B" => HandShape::Paper,
                "C" => HandShape::Scissors,
                _ => panic!("Not A/B/C"),
            };
            let hs2 = match &line[2..3] {
                "X" => HandShape::Rock,
                "Y" => HandShape::Paper,
                "Z" => HandShape::Scissors,
                _ => panic!("Not X/Y/Z"),
            };
            (hs1, hs2)
        })
        .collect()
}

#[allow(unused)]
fn part1() {
    let games = parse_input();
    let score = games
        .into_iter()
        .map(|(hs1, hs2)| -> i32 {
            hs2.play_game(&hs1)
        })
        .sum::<i32>();
    println!("Part 1: {}", score);
}

#[allow(unused)]
fn part2() {
    let input = include_str!("../input.txt");
    let score = input
        .lines()
        .map(|line| -> i32 {
            let elf_hand_shape = match &line[0..1] {
                "A" => HandShape::Rock,
                "B" => HandShape::Paper,
                "C" => HandShape::Scissors,
                _ => panic!("Not A/B/C"),
            };
            
            match &line[2..3] {
                "Z" => {
                    match elf_hand_shape {
                        HandShape::Rock => 6 + 2,
                        HandShape::Paper => 6 + 3,
                        HandShape::Scissors => 6 + 1, 
                    }
                }
                "Y" => {
                    match elf_hand_shape {
                        HandShape::Rock => 3 + 1,
                        HandShape::Paper => 3 + 2,
                        HandShape::Scissors => 3 + 3, 
                    }
                }
                "X" => {
                    match elf_hand_shape {
                        HandShape::Rock => 0 + 3,
                        HandShape::Paper => 0 + 1,
                        HandShape::Scissors => 0 + 2, 
                    }
                }
                _ => panic!("Not X/Y/Z"),
            }
        })
        .sum::<i32>();
    println!("Part 2: {}", score);

}

fn main() {
    part1();
    part2();
}
